<template>
    <div class="upload_cropper_container" :style="{ '--width': width, '--height': height }">
        <!--上传图片-->
        <el-upload action="#" :class="{single_file}" list-type="picture-card" :auto-upload="false"
                   :accept="uploadOptions.accept" :limit="uploadOptions.limit" :file-list="fileList"
                   :before-upload="beforeUpload" :on-change="changeUpload" :on-exceed="exceedUpload">
            <i slot="default" class="el-icon-plus"></i>
            <div slot="file" slot-scope="{file}">
                <img class="el-upload-list__item-thumbnail" :src="file.url" alt="">
                <span class="el-upload-list__item-actions">
                    <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
                      <i class="el-icon-zoom-in"></i>
                    </span>
                    <span v-if="isEditFlag" class="el-upload-list__item-delete" @click="handleRemove(file)">
                      <i class="el-icon-delete"></i>
                    </span>
                </span>
            </div>
            <template v-if="$utils.isNotEmpty(uploadOptions.tip)">
                <div slot="tip" class="el-upload__tip" v-html="uploadOptions.tip"/>
            </template>
        </el-upload>
    </div>
</template>

<script>
import {VueCropper} from 'vue-cropper'
import CropperArea from "./CropperArea.vue";

export default {
    name: "UploadCropper",
    components: {
        VueCropper,
    },
    props: {
        options: {
            type: Object,
            default: {},
        },
        data: {
            type: Array,
            default: [],
        },
        width: {
            type: String,
            default: '200px',
        },
        height: {
            type: String,
            default: '200px',
        },
        isEditFlag: {
            type: Boolean,
            default() {
                return true;
            }
        }
    },
    computed: {
        single_file() {
            let fileList = this.fileList;
            return (this.$utils.isNotEmptyList(fileList) && this.uploadOptions.limit === fileList.length) || !this.isEditFlag;
        },
    },
    watch: {
        options: {
            handler() {
                this.initOptions();
            },
            deep: true,
            immediate: true,
        },
        data: {
            handler() {
                this.initData(this.data);
            },
            deep: true,
            immediate: true,
        },
    },
    data() {
        return {
            fileList: [],
            dialogOptions: {
                visible: false,
            },
            cropperOptions: {},
            uploadOptions: {},
            defaultOptions: {
                uploadOptions: {
                    fileName: "",
                    accept: 'image/*',// 允许上传图片格式 image/gif, image/jpeg, image/png, image/jpg
                    limit: 1,// 允许上传图片数量，默认只上传1张
                    tolerate: 0.1, // 与默认大小的偏差容忍度，当图片实际大小与设定的大小偏差比例小于此值，则不进行裁剪就直接上传
                    tip: '',//图片区域下方显示的提示信息
                },
                dialogOptions: {
                    title: "裁剪",
                    visible: false,
                },
                cropperOptions: {
                    img: '', // 裁剪图片的地址
                    info: true, // 裁剪框的大小信息
                    outputQuanlity: 0.9, // 裁剪生成图片的质量
                    outputType: 'jpeg', // 裁剪生成图片的格式
                    canScale: true, // 图片是否允许滚轮缩放
                    autoCrop: true, // 是否默认生成截图框
                    autoCropWidth: 300, // 默认生成截图框宽度
                    autoCropHeight: 300, // 默认生成截图框高度
                    fixedBox: true, // 固定截图框大小 不允许改变
                    fixed: true, // 是否开启截图框宽高固定比例
                    fixedNumber: [], // 截图框的宽高比例
                    full: false, // 是否输出原图比例的截图
                    canMoveBox: false, // 截图框能否拖动
                    original: false, // 上传图片按照原始比例渲染
                    centerBox: false, // 截图框是否被限制在图片里面
                    infoTrue: true, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高 fileinfo:{}
                    canMove: true, // 是否可以拖动图片
                    enlarge: 1, // 倍数  可渲染当前截图框的n倍 0 - 1000;
                    high: false,//是否按照设备的dpr 输出等比例图片	true	true, false
                    maxImgSize: 2000,//	限制图片最大宽度和高度	2000	0 ~ max
                    mode: 'contain',//	图片默认渲染方式	contain	contain , cover, 100px, 100% auto
                },
            },
            uploadCropperData: {
                file_sid: undefined,
            },
            scale: 1,
            trueHeight: 0,
            trueWidth: 0,
            returnResList: [],
        }
    },
    beforeDestroy() {
        let _this = this;
        _this.fileList = [];
        _this.returnResList = [];
    },
    methods: {
        initOptions() {
            let _this = this;
            _this.dialogOptions = $.extend({}, _this.defaultOptions.dialogOptions);
            if (_this.options.dialogOptions) {
                _this.dialogOptions = $.extend({}, _this.dialogOptions, _this.options.dialogOptions);
            }
            _this.cropperOptions = $.extend({}, _this.defaultOptions.cropperOptions);
            if (_this.options.cropperOptions) {
                let cropW = 1;
                let cropH = _this.$utils.accDiv(_this.cropperOptions.autoCropHeight, _this.cropperOptions.autoCropWidth);
                if (_this.options.cropperOptions.autoCropHeight && _this.options.cropperOptions.autoCropWidth) {
                    cropH = _this.$utils.accDiv(_this.options.cropperOptions.autoCropHeight, _this.options.cropperOptions.autoCropWidth);
                }
                _this.cropperOptions = $.extend({}, _this.cropperOptions, {
                    ..._this.options.cropperOptions,
                    fixedNumber: [cropW, cropH],
                });
            }
            _this.uploadOptions = $.extend({}, _this.uploadOptions, _this.defaultOptions.uploadOptions);
            if (this.options.uploadOptions) {
                _this.uploadOptions = $.extend({}, _this.uploadOptions, _this.options.uploadOptions);
            }
        },
        initData(data) {
            let _this = this;
            _this.fileList = [];
            _this.returnResList = [];
            if (data && data.length > 0) {
                data.forEach(async (item, index) => {
                    // let url = await _this.getFileUrl(item.file_sid);
                    await _this.getFileInfoWithUrl(item.file_sid).then(fileInfo => {
                        _this.returnResList.push(fileInfo);
                        _this.fileList.push({
                            sid: fileInfo.sid,
                            name: fileInfo.original_file_name,
                            url: fileInfo.url,
                        });
                    });
                });
            }
        },
        // 文件状态改变时
        changeUpload(file, fileList) {
            let _this = this;
            if (file && file.name) {
                if (!_this.uploadOptions.accept) {
                    return;
                }
                // _this.uploadOptions.fileName = file.name;
                // let picSuffix = file.name.substring(file.name.lastIndexOf("."));
                // let regex = /\.(jpg|jpeg|png|JPG|PNG)$/;
                // let accept = _this.uploadOptions.accept.replace(/\./g, "").replace(/\“/g, "").replace(/\,/g, "|");
                // let acceptRegex = new RegExp(`.(${accept})$`, "g");
                // if (!acceptRegex.test(picSuffix)) {
                //     _this.$message.error("图片类型要求：jpeg、jpg、png");
                //     return false
                // }
                // 在插件上展示图片
                let imgUrl = URL.createObjectURL(file.raw);
                let img = new Image();
                // 解决跨域问题
                img.setAttribute('crossOrigin', 'anonymous');
                img.src = imgUrl;
                img.onload = () => {
                    let widthScale = Math.abs(_this.$utils.accDiv(img.width, _this.cropperOptions.autoCropWidth) - 1).toFixed(2);
                    let heightScale = Math.abs(_this.$utils.accDiv(img.height, _this.cropperOptions.autoCropHeight) - 1).toFixed(2);
                    // 宽度或者高度偏差比例大于设定值则剪切
                    if (widthScale > _this.uploadOptions.tolerate || heightScale > _this.uploadOptions.tolerate) {
                        _this.openCropperDialog(imgUrl);
                    } else {
                        let canvas = document.createElement("canvas");
                        canvas.width = img.width;
                        canvas.height = img.height;
                        let context = canvas.getContext('2d');
                        context.drawImage(img, 0, 0, img.width, img.height);
                        // 这里的dataurl就是base64类型
                        let dataURL = canvas.toDataURL("image/" + _this.cropperOptions.outputType, _this.cropperOptions.outputQuanlity);
                        const loading = this.$loading({
                            lock: true,
                            text: '正在上传图片........................',
                            spinner: 'el-icon-loading',
                            background: 'rgba(0, 0, 0, 0.7)',
                        });
                        // 使用toDataUrl将图片转换成jpeg的格式,不要把图片压缩成png，因为压缩成png后base64的字符串可能比不转换前的长！
                        _this.uploadFile(dataURL, loading);
                    }
                }
            }
        },
        openCropperDialog(img) {
            const _this = this;
            _this.$dialog({
                title: _this.dialogOptions.title,
                width: '890px',
                component: {
                    value: CropperArea,
                    props: {
                        options: {
                            ..._this.cropperOptions,
                            img,
                        },
                        upload: _this.uploadOptions,
                    },
                    event(event) {
                        console.log(event);
                        if (event.type === 'closeEvent') {
                            _this.fileList = [];
                            _this.returnResList = [];
                            return;
                        }
                        if (event.type === 'success') {
                            _this.fileList.push(event.obj);
                            _this.returnResList.push(event.data);
                            _this.$emit("success", _this.returnResList);
                        }
                    },
                },
            });
        },
        // 文件超出个数限制时的钩子
        exceedUpload(files, fileList) {
            this.$message.error(`最多只能上传${this.uploadOptions.limit}张图片！`);
        },
        // 上传文件之前
        beforeUpload() {
        },
        // 上传文件
        uploadFile(data, loading) {
            let _this = this;
            _this.storeDispatch('uploadBase64', {
                base64: data,
                associate_biz_table: _this.uploadOptions.associate_biz_table,
                associate_biz_sid: undefined,
                associate_biz_field_tag: _this.uploadOptions.associate_biz_field_tag,
            }).then(result => {
                let resData = result.data || {};
                let url = _this.getFileWithType(resData.sid, resData.file_type);
                let obj = {
                    sid: resData.sid,
                    name: resData.original_file_name,
                    url,
                };
                loading.close();
                _this.fileList.push(obj);
                _this.returnResList.push(resData);
                _this.$emit("success", _this.returnResList);
                // _this.uploadOptions.imgUrl = url;
                // _this.$emit("success", resData);
            }).catch(() => {
                loading.close();
                _this.$message.error("上传失败");
            });
        },
        // 移除
        handleRemove(file) {
            let _this = this;
            for (let i = 0; i < _this.fileList.length; i++) {
                if (file && file.uid && _this.fileList[i].uid === file.uid) {
                    _this.fileList.splice(i, 1);
                    _this.returnResList.splice(i, 1);
                }
            }
            _this.$emit("success", _this.returnResList);
        },
        // 查看
        handlePictureCardPreview(file) {
            window.open(file.url, '_blank')
        },
        // 下载
        handleDownload(file) {
            this.download(file.url, file.name);
        },
        download(src, fileName) {
            let x = new XMLHttpRequest();
            x.open("GET", src, true);
            x.responseType = 'blob';
            x.onload = function (e) {
                let url = window.URL.createObjectURL(x.response)
                let a = document.createElement('a');
                a.href = url
                a.download = fileName
                a.click()
            }
            x.send();
        },
        reloadUploadCropper() {
            let _this = this;
            _this.fileList = [];
            _this.returnResList = [];
        },
    }
}
</script>

<style lang="less" rel="stylesheet/less" scoped>
.rotate-list {
    margin-bottom: 6px;
}

.avatar {
    margin-top: 136px;
}

/deep/ .el-upload--picture-card {
    background-color: #fbfdff;
    border: 1px dashed #c0ccda;
    border-radius: 6px;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    width: var(--width);
    height: var(--height);
    line-height: var(--height);
    vertical-align: top;
}

/deep/ .el-upload--text {
    background-color: #fff;
    border: 1px dashed #d9d9d9;
    border-radius: 6px;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    width: var(--width);
    height: var(--height);
    text-align: center;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

/deep/ .el-upload-list--picture-card .el-upload-list__item {
    overflow: hidden;
    background-color: #fff;
    border: 1px solid #c0ccda;
    border-radius: 6px;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
    width: var(--width);
    height: var(--height);
    margin: 0 8px 8px 0;
    display: inline-block;
}

/deep/ .el-upload-list--picture-card .el-upload-list__item-thumbnail {
    width: var(--width);
    height: var(--height);
}

.single_file {
    /deep/ .el-upload--picture-card {
        display: none;
    }

    /deep/ .el-upload-list--picture-card {
        .el-upload-list__item {
            margin: 0;
        }
    }
}
</style>
